<template>
    <div class="pathView" id="pathView" ref="pathView">
        <a-spin :spinning="loadingState">
            <a-row class="chart">
                <div ref="sankeyContainer" id="d3-sankey">
                    <!-- <Spin size="large" fix v-if="loading"></Spin> -->
                    <div ref="nodeTooltip" v-show="tooltip.node.show" class="d3-node-tooltip" v-bind:style="{left: tooltip.node.left +'px', top: tooltip.node.top + 'px' }" style="z-index: 1000;">
                        <span style="color:rgba(0,0,0,0.85);">{{ tooltip.node.data.event_cname }}</span>
                        <br>
                        <span v-if="tooltip.node.data.dimensionValue" style="color:rgba(0,0,0,0.38);">{{ tooltip.node.data.dimensionValue }}</span>
                        <br v-if="tooltip.node.data.dimensionValue">
                        <span style="color:#00b279;">( {{ tooltip.node.data.value }} 会话数 )</span>
                        <div v-if="!tooltip.node.data.isEnd" class="node-detail" style="border-top:1px solid #e3e3e3;padding-top: 7px;">
                            <ul>
                                <li class="remain">
                                    <span>{{ tooltip.node.data.remain }} 留存量 ( {{ tooltip.node.data.remain_percent }} % )</span>
                                </li>
                                <li class="lost">
                                    <span>{{ tooltip.node.data.waste }} 流失量 ( {{ tooltip.node.data.wastage_percent }} % )</span>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div ref="linkTooltip" v-show="tooltip.link.show" class="d3-link-tooltip" v-bind:style="{left: tooltip.link.left +'px', top: tooltip.link.top + 'px' }" style="z-index: 1000;">
                        <span style="color:rgba(0,0,0,0.85);">{{ tooltip.link.data.source.event_cname }}</span>
                        <span style="color:rgba(0,0,0,0.85);">到</span>
                        <span style="color:rgba(0,0,0,0.85);">{{ tooltip.link.data.target.event_cname }}</span>
                        <div class="link-detail" style="border-top:1px solid #e3e3e3;padding-top: 5px;">
                            <span style="color:#00b279;">( {{ tooltip.link.data.value }} 会话数 )</span><br>
                            <span style="color:rgba(0,0,0,0.85);">总流量的 {{ tooltip.link.data.percentage }} %</span>
                        </div>
                    </div>
                    <div ref="contextMenu" v-show="contextMenu.show" class="d3-context-menu" style="z-index: 1200;" v-bind:style="{left: contextMenu.left +'px', top: contextMenu.top + 'px' }">
                        <div v-show="item.display.highLightPath">
                            <div v-if="!contextMenu.clicked" data-method="toggle-current-path">突出通过该节点的路径</div>
                            <div v-if="contextMenu.clicked" data-method="cancel-current-path">取消突出通过该节点的路径</div>
                        </div>
                        <div v-show="item.display.showDetails" data-method="detail">查看节点详细信息</div>
                    </div>
                </div>
                <a-modal
                        id="node-detail"
                        v-model="detail.show"
                        title="节点详细信息">
                    <div slot="footer">
                    </div>
                    <div class="modal-body">
                        <div class="node-event-title">
                            <span class="item-title">节点事件：</span>
                            <span class="item-value">{{detail.data.event_cname}}</span>
                        </div>
                        <div class="node-event-title">
                            <span class="item-title">分组属性值：</span>
                            <span class="item-value"><var>{{ detail.data.dimensionValue === "" ?  "无" : detail.data.dimensionValue  }}</var></span>
                        </div>
                        <div class="node-event-overview">
                            <table class="table">
                                <thead>
                                <tr>
                                    <th></th>
                                    <th style="width: 33%;">会话数</th>
                                </tr>
                                </thead>
                                <tbody>
                                <tr>
                                    <td>合计</td>
                                    <td>{{detail.data.value}}</td>
                                </tr>
                                <tr v-if="!detail.data.isEnd">
                                    <td><span>后续事件统计</span>&nbsp;<span style="color: #9fc3ec; font-size: 6px;">&#9632;</span></td>
                                    <td>{{detail.data.remain}} <span class="percentage">({{detail.data.remain_percent}} %)</span></td>
                                </tr>
                                <tr v-if="!detail.data.isEnd && detail.data.isInitialEvent">
                                    <td><span>流失</span>&nbsp;<span style="color: #ff7479; font-size: 6px;">&#9632;</span></td>
                                    <td>{{detail.data.waste}} <span class="percentage">({{detail.data.wastage_percent}} %)</span></td>
                                </tr>
                                </tbody>
                            </table>
                        </div>
                        <div class="node-event-detail" v-if="!detail.data.isEnd">
                            <table class="table table-fixedheader">
                                <thead>
                                <tr>
                                    <th v-if="detail.data.isInitialEvent">后续事件</th>
                                    <th v-if="!detail.data.isInitialEvent">前置事件</th>
                                    <th>分组值</th>
                                    <th>会话数</th>
                                </tr>
                                </thead>
                                <tbody>
                                <template v-if="detail.data.isInitialEvent">
                                    <tr v-for="item in detail.data.sourceLinks" :key="item.id" v-if="!item.is_wastage">
                                        <td>{{item.target.event_cname}}</td>
                                        <td>{{ item.target.dimensionValue ?  item.target.prop +":" + item.target.dimensionValue : "无" }}
                                        </td>
                                        <td>{{item.value}} <span class="percentage">({{item.percent}} %)</span>
                                        </td>
                                    </tr>
                                </template>
                                <template v-else>
                                    <tr v-for="item in detail.data.sourceLinks" :key="item.id" v-if="!item.is_wastage">
                                        <td>{{item.source.event_cname}}</td>
                                        <td>{{ item.source.dimensionValue ? item.source.prop +":" +item.source.dimensionValue : "无" }}</td>
                                        <td>{{item.value}} <span class="percentage">({{item.percent}} %)</span></td>
                                    </tr>
                                </template>

                                </tbody>
                            </table>
                        </div>
                    </div>
                </a-modal>
            </a-row>
        </a-spin>
    </div>
</template>

<script>
import '@/views/components/d3';
import '@/views/components/d3-sankey';
import $ from "jquery";
import { mapActions, mapState } from 'vuex';
import elementResize from '@/views/reportForms/show_report/elementResize';
export default {
    props: {
        item: Object,
        dataApkdb: Object,
        rowHeight: Number,
        loadingState: Boolean
    },
    data () {
        return {
            tooltip: {
                node: {
                    show: false,
                    left: 0,
                    top: 0,
                    data: {
                        value: 0,
                        event_cname: "",
                        remain: 0,
                        wastage: 0,
                        remain_percent: 0,
                        wastage_percent: 0
                    }
                },
                link: {
                    show: false,
                    left: 0,
                    top: 0,
                    data: {
                        source: {
                            event_cname: ""
                        },
                        target: {
                            event_cname: ""
                        },
                        value: 0,
                        percentage: 0
                    }
                }
            },
            sankeyOption: {
                domSize: 160,
                defaultLayers: 4,
                opacity: {
                    transStrokeOpacity: 0,
                    lightStrokeOpacity: .3,
                    darkStrokeOpacity: 1,
                    midStrokeOpacity: .8
                },
                color: {
                    link_light_color: "#E1EBF7",
                    link_dark_color: "#BBCDE3",
                    link_light_rgb: "rgb(225, 235, 247)",
                    link_dark_rgb: "rgb(187, 205, 227)"
                },
                screen: {
                    width: 1400,
                    height: 800,
                    margin: {
                        top: 25,
                        right: 25,
                        bottom: 25,
                        left: 25
                    }
                },
                colors: [],
                inEmptyNode: {
                    event_cname: "起始",
                    event_name: "start",
                    sourceLinks: [],
                    targetLinks: [],
                    isStart: !0
                }
            },
            contextMenu: {
                show: false,
                left: 0,
                top: 0,
                clicked: false,
            },
            detail: {
                show: false,
                data: {
                    event_cname: "",
                    dimensionValue: "",
                    isInitialEvent: false,
                    isEnd: false,
                },
            },
            config: {},
            data: {},
            currentLayer: 3,
            datasourceId: null,
            limit: {},
            bindVal: false
        }
    },
    watch: {
      //监听数据集数据变化并重新渲染
      dataApkdb(newVal, oldVal) {
        this.render();
      }
    },
    computed: {
        ...mapState('analyseType', ['events', 'propertiesEvent', 'propertiesUser']),
        inputTargetType: function () {
            return this.config.endpoint.type === 0 ? "initial_event" : "termination_event";
        },
        inputTargetTypeLabel: function () {
            return this.config.endpoint.type === 0 ? "起始事件" : "结束事件";
        },
        properties: function () {
            return [...this.propertiesEvent, ...this.propertiesUser];
        }
    },
    methods: {
        ...mapActions('analyseType',['getPropertiesEvent_report', 'getPropertiesUser_report', 'getEvents']),
        ...mapActions('custom', ['getUpdateReportDs']),
        async initPathView () {
            let datasetId = this.item.dataMapping.datasetId;
            await this.getUpdateReportDs({id: datasetId})
                .then(res => {
                    this.datasourceId = res.data.datasourceId;
                    this.config = JSON.parse(res.data.config).config;
                    this.limit = JSON.parse(res.data.config).limit;
                })
            await this.getPropertiesEvent_report({id: this.datasourceId});
            await this.getPropertiesUser_report({id: this.datasourceId});
            await this.getEvents(this.datasourceId);
            await this.get_path_data();
        },
        getEventDisplayName: function(event) {
            for(let i = 0; i < this.events.length; i++) {
                if(this.events[i].name === event) {
                    return this.events[i].displayName;
                }
            }
            return "无";
        },
        get_path_data () {
            this.data = this.dataApkdb[this.item.dataMapping.datasetId];
            if (!this.data) {
                return
            }
            this.currentLayer = this.data.nodes ? this.data.nodes.length : 3;
            this.data.links.forEach(function(e) {
                for (var t = 0; t < e.length; t++) {
                    if (e[t].is_wastage === !0) {
                        var n = e[t];
                        for(var j = e.length - 1; j > t; j--) {
                            if(e[j].is_wastage === !0) {
                                continue;
                            }
                            e[t] = e[j];
                            e[j] = n;
                            break;
                        }

                    }
                }
            });
            if (this.config.events) {
                this.renderSankey();
            }
        },
        //渲染桑基图
        renderSankey: function() {
            d3.select("#d3-sankey svg").remove();
            this.initSankey("d3-sankey", this.formatSankeyData(this.currentLayer));
            this.initSankeyEvents();
        },
        //初始化桑基图
        initSankey: function(e, t) {
            function n() {
                for (var e = d3.select(this), t = e.node().getComputedTextLength(), n = e.text(); t > 100 && n.length > 0;) n = n.slice(0, -1),
                    e.text(n + "..."),
                    t = e.node().getComputedTextLength()
            }
            var a = this;
            var i = t,
                r = this.sankeyOption.screen.margin,
                s = this.sankeyOption.screen.width - r.left - r.right,
                o = this.sankeyOption.screen.height - r.top - r.bottom,
                l = "initial_event" === this.inputTargetType ? "ltr": "rtl",
                d = d3.select("#" + e).append("svg").attr("width", s + r.left + r.right).attr("height", o + r.top + r.bottom).append("g").attr("transform", "translate(" + r.left + "," + r.top + ")"),
                p = d.append("defs").append("linearGradient").attr("id", "gradient").attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").attr("spreadMethod", "pad").attr("gradientUnits", "objectBoundingBox");
            p.append("stop").attr("offset", "0%").attr("stop-color", "#bfdcff").attr("stop-opacity", 1),
                p.append("stop").attr("offset", "100%").attr("stop-color", "#96bcea").attr("stop-opacity", 1);
            var c = d.append("defs").append("linearGradient").attr("id", "waste_gradient").attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").attr("spreadMethod", "pad").attr("gradientUnits", "objectBoundingBox");
            c.append("stop").attr("offset", "0%").attr("stop-color", "#F9C6C6").attr("stop-opacity", 1),
                c.append("stop").attr("offset", "100%").attr("stop-color", "white").attr("stop-opacity", 1);
            var u = d.append("defs").append("linearGradient").attr("id", "start_gradient").attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").attr("spreadMethod", "pad").attr("gradientUnits", "objectBoundingBox");
            u.append("stop").attr("offset", "0%").attr("stop-color", "#A9E3D1").attr("stop-opacity", 1),
                u.append("stop").attr("offset", "100%").attr("stop-color", "white").attr("stop-opacity", 1);
            var h = d3.sankey().nodeWidth(this.sankeyOption.domSize).size([s, o]).graphType(l),
                _ = h.link();
            h.nodes(i.nodes).links(i.links).layout(20);
            var v = d.append("g").selectAll(".link").data(i.links).enter().append("path");
            v.attr("class",
                function(e) {
                    return e.is_wastage ? "link wastage": e.isStart ? "link start": "link"
                }).attr("d", _).attr("link-id",
                function(e, t) {
                    return e.id = t,
                    "link-" + t
                }).style("stroke-width",
                function(e) {
                    return e.hasOwnProperty("is_wastage") && e.is_wastage === !0 ? Math.min(Math.max(5, e.dy / 8), 10) : e.hasOwnProperty("isStart") && e.isStart === !0 ? Math.min(Math.max(5, e.dy / 8), 10) : void 0
                }).style("stroke",
                function(e) {
                    return e.hasOwnProperty("is_wastage") && e.is_wastage === !0 ? "url(#waste_gradient)": e.hasOwnProperty("isStart") && e.isStart === !0 ? "url(#start_gradient)": void 0
                }).sort(function(e, t) {
                return t.dy - e.dy
            });
            var y = d.append("g").selectAll(".node").data(i.nodes).enter().append("g").attr("class", "node").attr("data-id",
                function(e) {
                    return e.event_name
                }).attr("transform",
                function(e) {
                    return "translate(" + e.x + "," + e.y + ")"
                }).sort(function(e, t) {
                return t.dy - e.dy
            });
            y.append("rect").attr("height",
                function(e) {
                    return Math.max(e.dy / 2, 1)
                }).attr("width", h.nodeWidth()).style("fill",
                function() {
                    return "url(#gradient)"
                }).attr("rx", 2).attr("ry", 2).attr("data-id",
                function(e) {
                    return e.id
                }).attr("data-cname",
                function(e) {
                    return e.event_cname
                }).style("transform",
                function(e) {
                    return "translate(0," + e.dy / 2 + ")"
                }).style("stroke",
                function() {
                    return "rgba(0,0,0,0.2)"
                }),
                y.append("text").attr("x", "12px").attr("y", "12px").attr("dy", ".35em").text(function(e) {
                    return e.event_cname
                }).style("font-weight", "400").each(n),
                y.append("text").attr("x", "12px").attr("y",
                    function(e) {
                        return e.dimensionValue ? "2.5em": "2em"
                    }).text(function(e) {
                    return e.dimensionValue
                }).style("font-size", "13px").style("fill", "rgba(0,0,0,0.54)").each(n),
                y.append("text").attr("x", "12px").attr("y",
                    function(e) {
                        return e.dimensionValue ? "3.5em": "2em"
                    }).attr("dy", ".35em").text(function(e) {
                    return e.value
                });
            var f = null,
                m = this.inputTargetType,
                g = [];
            switch (m) {
                case "termination_event":
                    g = this.data.nodes[this.data.nodes.length - 1],
                        f = g[g.length - 1].event_name;
                    break;
                case "initial_event":
                    g = this.data.nodes[0],
                        f = g[g.length - 1].event_name
            }
            d3.select('[data-id="' + f + '"]').append("svg:foreignObject").attr("width", 100).attr("height", "2em").attr("y",
                function(e) {
                    return e.dy / 2 - 40
                }).attr("x", "1.5em").append("xhtml:div").attr("class", "label_event").html(function() {
                return "<span>" + this.inputTargetTypeLabel.html() + "</span><span class='icon-event-direction'></span>"
            })
        },
        //格式化桑基图数据
        formatSankeyData: function(e) {
            var t = {
                nodes: [],
                links: []
            };
            if (0 === this.config.events.length) return t;
            if ((!e || e > this.data.nodes.length) && (e = this.data.nodes.length, this.maxLayer = this.data.nodes.length), 0 === this.data.nodes.length || 0 === this.data.links.length) return this.data;
            var n = 130 * (e - 1) + 130 * e;
            this.sankeyOption.screen.width = this.$refs.sankeyContainer.clientWidth > n ? this.$refs.sankeyContainer.clientWidth : n,
                this.sankeyOption.screen.height = this.limit.node * 100;
            var a, i = this.data;
            switch (this.inputTargetType) {
                case "initial_event":
                    for (a = 0; e - 1 > a; a++) t.nodes = t.nodes.concat(i.nodes[a]),
                        t.links = t.links.concat(i.links[a]);
                    t.nodes = t.nodes.concat(i.nodes[a]),
                    1 === t.nodes.length && (t.links = t.links.concat(i.links[0]));
                    break;
                case "termination_event":
                    var r = i.nodes.length;
                    for (a = r - e; r - 1 > a; a++) t.nodes = t.nodes.concat(i.nodes[a]),
                        t.links = t.links.concat(i.links[a]);
                    t.nodes = t.nodes.concat(i.nodes[r - 1]),
                    0 === t.links.length && t.links.push({
                        isStart: !0,
                        source: "1_start",
                        target: t.nodes[0].id,
                        times: t.nodes[0].value
                    })
            }
            this.nodeMap = {};
            var s = this;
            t.nodes.forEach(function(e) {
                if (s.nodeMap[e.id] = e, e.hasOwnProperty("dimensionValue") && s.config.dimension) {
                    var t = (s.config.dimension || []).map(function(e) {
                            var t = e.split("."),
                                n = t[1],
                                a = t[2];
                            return {
                                event: n,
                                prop: a
                            }
                        }).filter(function(t) {
                            return t.event === e.event
                        })[0] || {},
                        n = (s.properties.filter(function(e) {
                            return e.name === "events."+t.prop
                        })[0] || {}).type;
                    "bool" === (n || "").toLowerCase() && (e.dimensionValue = parseInt(e.dimensionValue, 10) ? "是": "否")
                }
                e.event_cname = "more" === e.event ? "更多" : s.getEventDisplayName(e.event) || "未知"
            });
            t.links = t.links.map(function(e) {
                var t = {
                    source: s.nodeMap[e.source],
                    target: s.nodeMap[e.target],
                    value: e.times
                };
                if(e.hasOwnProperty("is_wastage") && e.is_wastage === !0) {
                    t.is_wastage = !0;
                    s.nodeMap[e.source].waste = e.times;
                } else {
                    if(e.hasOwnProperty("isStart")) {
                        t.is_wastage = !1;
                        t.isStart = !0;
                    } else {
                        t.is_wastage = !1;
                        s.nodeMap[e.source].waste = 0;
                    }
                }
                return t;
            });
            return t;
        },
        //初始化tooltip
        initTooltip: function() {
            //设置link的mouseoer事件
            let _self = this;
            var sankeyContainer = document.getElementById("d3-sankey");
            d3.selectAll(".link")
                .on("mouseover", function(d) {
                    var position = d3.mouse(sankeyContainer);
                    if(parseFloat(d3.select(this).style("stroke-opacity")) !== _self.sankeyOption.opacity.lightStrokeOpacity && !_self.contextMenu.show) {
                        d.percentage = d.isStart === !0 ? Math.round(d.value / d.target.value * 1e4) / 100 : Math.round(d.value / d.source.value * 1e4) / 100;
                        if(d3.select(this).style("stroke") === _self.sankeyOption.color.link_light_rgb) {
                            d3.select(this).style("stroke", _self.sankeyOption.color.link_dark_color).style("fill", _self.sankeyOption.color.link_dark_color);
                        }
                        _self.tooltip.link.left = position[0];
                        _self.tooltip.link.top = position[1]+20;
                        _self.tooltip.link.show = true;
                        _self.tooltip.link.data = d;
                    }
                })
                .on("mousemove",
                    function() {
                        var position = d3.mouse(sankeyContainer);
                        if(position[0] + _self.$refs.linkTooltip.clientWidth > _self.$refs.sankeyContainer.scrollLeft + _self.$refs.sankeyContainer.clientWidth) {
                            position[0] = position[0] - _self.$refs.linkTooltip.clientWidth;
                        }
                        _self.tooltip.link.left = position[0];
                        _self.tooltip.link.top = position[1]+20;

                }).on("mouseout",
                    function() {
                        _self.tooltip.link.show = false;
                        var e = parseFloat(d3.select(this).style("stroke-opacity"));
                        e !== _self.sankeyOption.opacity.midStrokeOpacity ||
                            _self.flag ||
                            d3.select(this)
                                .style("stroke", _self.sankeyOption.color.link_light_color)
                                .style("fill", _self.sankeyOption.color.link_light_color);
                });
            d3.selectAll(".node")
                .on("mouseover",
                    function (d) {
                        var position = d3.mouse(sankeyContainer);
                        if(0 === d.sourceLinks.length) {
                            d.isEnd = true
                        } else {
                            d.remain = d.value - d.waste;
                            d.wastage_percent = Math.round(d.waste / d.value * 1e4) / 100;
                            d.remain_percent = Math.round(d.remain / d.value * 1e4) / 100
                        }
                        if(parseFloat(d3.select('[data-id="' + d.id + '"]').style("opacity")) !== _self.sankeyOption.opacity.lightStrokeOpacity
                            && !_self.contextMenu.show) {
                            d.isInitialEvent = "initial_event" === _self.inputTargetType;
                            _self.tooltip.node.left = position[0];
                            _self.tooltip.node.top = position[1]+20;
                            _self.tooltip.node.show = true;
                            _self.tooltip.node.data = d;
                        }

                }).on("mousemove",
                    function () {
                        var position = d3.mouse(sankeyContainer);
                        if(position[0] + _self.$refs.nodeTooltip.clientWidth > _self.$refs.sankeyContainer.scrollLeft + _self.$refs.sankeyContainer.clientWidth) {
                            position[0] = position[0] - _self.$refs.nodeTooltip.clientWidth;
                        }
                        _self.tooltip.node.left = position[0];
                        _self.tooltip.node.top = position[1]+20;
                }).on("mouseout",
                    function () {
                        _self.tooltip.node.show = false;
                });
        },
        //初始化上下文菜单
        initContextMenu: function() {
            let _self = this;
            var sankeyContainer = document.getElementById("d3-sankey");
            d3.selectAll(".node")
                .on("click",
                    function(d) {
                        var position = d3.mouse(sankeyContainer);
                        _self.tooltip.node.show = false;
                        _self.contextMenu.show = false;
                        _self.contextMenu.left = position[0];
                        _self.contextMenu.top = position[1]+20;
                        _self.contextMenu.clicked = "1" === $(this).attr("data-clicked");
                        _self.contextMenu.show = true;
                        _self.initContextMenuEvents(d, this);
                });

            $.fn.slider = function() {
                return this.each(function() {
                    var e = $(this),
                        n = !1,
                        a = 0;
                    e.mousedown(function(e) {
                        n = !0,
                            a = e.clientX;
                        var r = $("#d3-sankey").scrollLeft(),
                            s = !1;
                        $(this).unbind("mousemove").bind("mousemove",
                            function(e) {
                                if (n) {
                                    var i = e.clientX - a;
                                    $("#d3-sankey").scrollLeft(r - i),
                                        s = !0
                                }
                            }),
                            $(this).unbind("mouseup").bind("mouseup",
                                function(e) {
                                    if (n = !1, !s) {
                                        var a = $(e.target || e.srcElement); (a.is("svg") || 1 === a.parents("svg").length) && _self.contextMenu.show && (_self.contextMenu.show = !1)
                                    }
                                    s = !1
                                })
                    })
                })
            },
                $("#d3-sankey").slider();
        },
        //初始化上下文菜单操作事件
        initContextMenuEvents: function(nodeData, nodeEl) {
            var _self = this;
            var r = function(e, t) {
                if (0 === e.size) return ! 1;
                var n = !1;
                return e.forEach(function(e) {
                    e === t && (n = !0)
                }),
                    n
            };
            var o = function(e, t) {
                d3.select('[data-id="' + e + '"]').transition().style("opacity", t),
                    $('[data-id="' + e + '"]').siblings().css("opacity", t)
            };
            var highlightPath = function(e) {
                var n = this,
                    a = d3.selectAll("rect");
                d3.selectAll(".link").style("stroke", _self.sankeyOption.color.link_light_color).style("fill", _self.sankeyOption.color.link_light_color).style("stroke-opacity", _self.sankeyOption.opacity.midStrokeOpacity).style("fill-opacity", _self.sankeyOption.opacity.midStrokeOpacity);
                var i = [],
                    s = [],
                    l = _self.sankeyOption.opacity.transStrokeOpacity,
                    d = _self.sankeyOption.opacity.transStrokeOpacity,
                    p = null;
                "1" === d3.select(n).attr("data-clicked") ? (_self.flag = !1, d3.select(n).attr("data-clicked", "0"), p = _self.sankeyOption.color.link_light_color, d = _self.sankeyOption.opacity.midStrokeOpacity, l = _self.sankeyOption.opacity.darkStrokeOpacity, a.filter(function() {
                    return n !== this
                }).transition().style("opacity",
                    function(e) {
                        return $('[data-id="' + e.id + '"]').siblings().css("opacity", _self.sankeyOption.opacity.darkStrokeOpacity),
                            _self.sankeyOption.opacity.darkStrokeOpacity
                    })) : (d3.select(n).attr("data-clicked", "1"), _self.flag = !0, p = _self.sankeyOption.color.link_dark_color, d = _self.sankeyOption.opacity.midStrokeOpacity, l = _self.sankeyOption.opacity.darkStrokeOpacity, a.filter(function() {
                    return n !== this
                }).transition().style("opacity",
                    function(e) {
                        return $('[data-id="' + e.id + '"]').siblings().css("opacity", _self.sankeyOption.opacity.lightStrokeOpacity),
                            _self.sankeyOption.opacity.lightStrokeOpacity
                    })),
                    d3.selectAll("g.node").filter(function() {
                        return n !== this
                    }).attr("data-clicked", null),
                    o(e.id, l);
                var c = [{
                        linkType: "sourceLinks",
                        nodeType: "target"
                    },
                        {
                            linkType: "targetLinks",
                            nodeType: "source"
                        }],
                    u = [];
                c.forEach(function(n) {
                    for (e[n.linkType].forEach(function(e) {
                        i = _self.mergeArray(i, [e[n.nodeType]]),
                            o(e[n.nodeType].id, l),
                            d3.select('[link-id="link-' + e.id + '"]').transition().style("stroke-opacity", d).style("stroke", p).style("fill-opacity", d).style("fill", p),
                            u.push(e.id)
                    }); i.length;) s = [],
                        i.forEach(function(e) {
                            e[n.linkType].forEach(function(e) {
                                s = _self.mergeArray(s, [e[n.nodeType]]),
                                    o(e[n.nodeType].id, l),
                                    u.push(e.id),
                                    d3.select('[link-id="link-' + e.id + '"]').transition().style("stroke-opacity", d).style("stroke", p).style("fill-opacity", d).style("fill", p)
                            })
                        }),
                        i = s
                }),
                    _self.flag ? d3.selectAll(".link").filter(function(e) {
                        return ! r(u, e.id)
                    }).transition().style("stroke-opacity",
                        function() {
                            return _self.sankeyOption.opacity.lightStrokeOpacity
                        }).style("fill-opacity",
                        function() {
                            return _self.sankeyOption.opacity.lightStrokeOpacity
                        }) : d3.selectAll(".link").filter(function(e) {
                        return ! r(u, e.id)
                    }).transition().style("stroke-opacity",
                        function() {
                            return _self.sankeyOption.opacity.midStrokeOpacity
                        }).style("fill-opacity",
                        function() {
                            return _self.sankeyOption.opacity.midStrokeOpacity
                        });
            };
            d3.selectAll(".d3-context-menu")
                .selectAll("div[data-method]")
                .on("click", function() {
                    var a = $(this).attr("data-method");
                    switch (a) {
                        case "toggle-current-path":
                            highlightPath.apply(nodeEl, [nodeData]);
                            break;
                        case "cancel-current-path":
                            _self.flag = !1,
                                    d3.selectAll("rect").transition().style("opacity",
                                        function(e) {
                                            return $('[data-id="' + e.id + '"]').siblings().animate({
                                                opacity: _self.sankeyOption.opacity.darkStrokeOpacity
                                            }),
                                                _self.sankeyOption.opacity.darkStrokeOpacity
                                        }),
                                    d3.selectAll(".link").transition().style("stroke-opacity", _self.sankeyOption.opacity.midStrokeOpacity).style("stroke", _self.sankeyOption.color.link_light_color).style("fill-opacity", _self.sankeyOption.opacity.midStrokeOpacity).style("fill", _self.sankeyOption.color.link_light_color),
                                    d3.selectAll("g.node").attr("data-clicked", null);
                                break;
                            case "detail":
                                nodeData.isInitialEvent = "initial_event" === _self.inputTargetType,
                                    nodeData.isEnd = !nodeData.sourceLinks.length,
                                    nodeData.sourceLinks.forEach(function(n, a) {
                                        var i = nodeData.sourceLinks[a].target,
                                            r = n.value / nodeData.remain;
                                        if (nodeData.sourceLinks[a].percent = _self.isFloat(r) ? (100 * r).toFixed(2) : 1 === r ? 100 : r, i.hasOwnProperty("dimensionValue")) {
                                            var s = i.event,
                                                o = i.id.slice(s.length + 1 + i.id.indexOf("_")),
                                                l = o.slice(1, o.lastIndexOf("_")),
                                                d = _self.properties.filter(function(e) {
                                                    return e.name === "events."+l
                                                }),
                                                p = d.length > 0 ? d[0].displayName: "未知";
                                            nodeData.sourceLinks[a].target.prop = p
                                        }
                                    }),
                                    nodeData.targetLinks.forEach(function(n, a) {
                                        var i = nodeData.targetLinks[a].source,
                                            r = n.value / nodeData.remain;
                                        if (nodeData.targetLinks[a].percent = _self.isFloat(r) ? (100 * r).toFixed(2) : r, i.hasOwnProperty("dimensionValue")) {
                                            var s = i.event,
                                                o = i.id.slice(s.length + 1 + i.id.indexOf("_")),
                                                l = o.slice(1, o.lastIndexOf("_")),
                                                d = _self.properties.filter(function(e) {
                                                    return e.name === "events."+l
                                                }),
                                                p = d.length > 0 ? d[0].displayName: "未知";
                                            nodeData.targetLinks[a].source.prop = p
                                        }
                                    }); //,
                                _self.detail.show = true;
                                _self.detail.data = nodeData;
                                break;
                            case "more":
                        }
                        _self.contextMenu.show = false;
                });
        },
        //初始化桑基图事件
        initSankeyEvents: function(){
            this.initTooltip();
            this.initContextMenu();
        },
        //合并数组
        mergeArray: function(e, t) {
            for (var n = e.concat(t), a = 0; a < n.length; ++a) for (var i = a + 1; i < n.length; ++i) n[a].id === n[i].id && n.splice(i--, 1);
            return n
        },
        //判断是否float
        isFloat: function(t) {
            return -1 !== (t + "").toString().indexOf(".");
        },
        reset_sankeyHeight () {
            let gridHeight = this.item.position.h * this.rowHeight,
                marginHeight = (this.item.position.h-1) * 10
            if (this.item.remark) {
                this.$refs.sankeyContainer.style.height = (gridHeight + marginHeight - 70)+ 'px';
            } else {
                this.$refs.sankeyContainer.style.height = (gridHeight + marginHeight - 50)+ 'px';
            }
        },
        //根据新数据渲染路径分析图
        render() {
          d3.select("#d3-sankey svg").remove();
          this.get_path_data();
        }
    },
    mounted () {
        this.initPathView();
        this.reset_sankeyHeight();
        elementResize.on(document.getElementById('pathView'), () => {
            let gridHeight = this.item.position.h * this.rowHeight,
                marginHeight = (this.item.position.h-1) * 10
            if (this.item.remark) {
                this.$refs.sankeyContainer.style.height = (gridHeight + marginHeight - 70)+ 'px';
            } else {
                this.$refs.sankeyContainer.style.height = (gridHeight + marginHeight - 50)+ 'px';
            }
        })
    },
    created () {}
}
</script>

<style>
    .pathView {
        width: 100%;
        height: calc(100% - 30px);
    }

    .pathView .chart{
        height: 100%;
        width: 100%;
    }

    #d3-sankey {
        overflow-x: scroll;
        cursor: grab;
        box-shadow: inset 1px 1px 4px 0 rgba(0,0,0,.2);
        border-radius: 3px;
        border: 1px solid rgba(0,0,0,.06);
        margin: 0 4px 0px
    }

    #d3-sankey .node rect {
        cursor: pointer;
        shape-rendering: crispEdges;
        background-image: linear-gradient(-180deg,#bfdcff 0,#96bcea 100%);
        border: 1px solid rgba(0,0,0,.06);
        box-shadow: 0 2px 2px 0 rgba(0,0,0,.2);
        border-radius: 1px
    }

    #d3-sankey .link {
        fill: #E1EBF7;
        stroke: #E1EBF7;
        stroke-opacity: .8;
        fill-opacity: .8
    }

    #d3-sankey .node {
        border-radius: 10px
    }

    #d3-sankey .link.wastage {
        stroke: url(#waste_gradient)!important
    }

    #d3-sankey .link.start {
        stroke: url(#start_gradient)!important
    }

    #d3-sankey .d3-node-tooltip {
        font-size: 13px;
        font-weight: 400;
        min-width: 175px;
        padding: 8px 10px 10px;
        position: absolute;
        text-align: center;
        background: #fff;
        border: 1px solid #b0b0b0;
        border-radius: 4px
    }

    #d3-sankey .d3-node-tooltip div.node-detail {
        margin-top: 5px
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul {
        margin-bottom: 0;
        text-align: left
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul li {
        list-style: none
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul li>span {
        color: rgba(0,0,0,.87)
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul li:before {
        content: '\2027';
        line-height: 20px;
        vertical-align: bottom;
        font-size: 60px
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul li.remain {
        color: #a6c3e8
    }

    #d3-sankey .d3-node-tooltip div.node-detail ul li.lost {
        color: rgba(240,70,70,.7)
    }

    #d3-sankey .d3-link-tooltip {
        font-size: 13px;
        font-weight: 400;
        min-width: 175px;
        width: auto;
        height: auto;
        position: absolute;
        text-align: center;
        padding: 8px 13px;
        background: #fff;
        border: 1px solid #b0b0b0;
        border-radius: 4px
    }

    #d3-sankey .d3-link-tooltip div.link-detail {
        margin-top: 7px
    }

    #d3-sankey .d3-context-menu {
        position: absolute;
        text-align: left;
        background-color: #fff;
        border: 1px solid rgba(0,0,0,.12);
        box-shadow: 0 2px 2px 0 rgba(0,0,0,.38);
        color: rgba(0,0,0,.87);
        min-width: 120px
    }

    #d3-sankey .d3-context-menu [data-method] {
        padding: 5px 15px
    }

    #d3-sankey .d3-context-menu [data-method]:hover {
        background: rgba(0,0,0,.06);
        cursor: pointer
    }

    #node-detail div.node-event-title {
        padding: 11px 25px;
        font-weight: 400;
        font-size: 13px
    }

    #node-detail div.node-event-title span.item-value {
        color: rgba(0,0,0,.87);
        margin-right: 90px
    }

    #node-detail div.node-event-overview {
        padding: 0;
        border-top: 1px solid rgba(0,0,0,.12)
    }

    #node-detail div.node-event-overview table>tbody>tr>td {
        padding-left: 25px;
        font-size: 13px;
        color: rgba(0,0,0,.87)
    }

    #node-detail div.node-event-overview table>tbody>tr>td:first-child {
        font-weight: 700
    }

    #node-detail div.node-event-overview table>thead>tr>th {
        padding-left: 25px
    }

    #node-detail div.node-event-detail {
        /*padding: 11px 0;*/
        border-top: solid 1px rgba(0,0,0,.12)
    }

    #node-detail div.node-event-detail table>thead>tr>th {
        width: 33%;
        max-width: 33%;
        min-width: 33%;
        display: inline-block;
        display: -moz-grid;
        padding-left: 25px;
    }

    #node-detail div.node-event-detail table>thead>tr>th:first-child {
        width: 50%
    }

    #node-detail div.node-event-detail table>tbody>tr>td {
        padding-left: 25px;
        font-size: 13px;
        color: rgba(0,0,0,.87)
    }

    #node-detail div.node-event-detail table.table-fixedheader {
        width: 100%
    }

    #node-detail div.node-event-detail table.table-fixedheader,div.node-event-detail table.table-fixedheader>thead,div.node-event-detail table.table-fixedheader>tbody,div.node-event-detail table.table-fixedheader>thead>tr,div.node-event-detail table.table-fixedheader>tbody>tr,div.node-event-detail table.table-fixedheader>thead>tr>th,div.node-event-detail table.table-fixedheader>tbody>td {
        display: block
    }

    #node-detail div.node-event-detail table.table-fixedheader>thead>tr:after,div.node-event-detail table.table-fixedheader>tbody>tr:after {
        content: ' ';
        display: block;
        visibility: hidden;
        clear: both
    }

    #node-detail div.node-event-detail table.table-fixedheader>tbody {
        overflow-y: scroll;
        max-height: 200px
    }

    #node-detail div.node-event-detail table.table-fixedheader>tbody>tr>td {
        width: 33%
    }

    #node-detail div.node-event-detail table.table-fixedheader>thead {
        overflow-y: scroll;
        display: inline
    }

    #node-detail div.node-event-detail table.table-fixedheader>thead::-webkit-scrollbar {
        background-color: inherit
    }

    #node-detail div.node-event-detail table.table-fixedheader>thead>tr>th:after,div.node-event-detail table.table-fixedheader>tbody>tr>td:after {
        content: ' ';
        display: table-cell;
        visibility: hidden;
        clear: both
    }

    #node-detail div.node-event-detail table.table-fixedheader>thead tr th,div.node-event-detail table.table-fixedheader>tbody tr td {
        float: left;
        word-wrap: break-word
    }

    #node-detail span.icon-user-analysis {
        color: #559FF0;
        cursor: pointer;
        text-decoration: none
    }

    #node-detail table {
        background: #FDFDFE;
        border-top: 2px solid #2DCA93;
        border-bottom: 1px solid #C3E6D0;
        font-weight: 400;
        font-size: 15px;
        width: 100%;
        max-width: 100%;
        /*margin-bottom: 20px;*/
    }

    #node-detail table>thead {
        background: #FDFDFE;
        color: #777C7C;
        -webkit-text-fill-color: #777C7C;
    }

    #node-detail table, #node-detail table>thead>tr>th, #node-detail table>tbody>tr>td {
        border: 0;
        padding: 8px;
        line-height: 1.42857143;
        text-align: left;
    }

    #node-detail table>thead>tr>th:last-child, #node-detail table>tbody>tr>td:last-child {
        text-align: left
    }

    #node-detail table>thead>tr>th {
        font-size: 13px;
        color: rgba(0,0,0,.87);
        background: #f9f9fa!important;
        text-align: left;
    }

    #node-detail ul li {
        list-style: none
    }

    #node-detail span.percentage {
        font-size: 13px;
        color: rgba(0,0,0,.54)
    }
</style>
